﻿using Iesi.Collections;
using Inovout.Kuajing.Models;
using Inovout.Kuajing.Services;
using Inovout.Kuajing.Web.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Web.Http;

namespace Inovout.Kuajing.Web.Controllers
{
    public class TradeController : ApiController
    {
        private static CommodityService commodityService = ComponentRegistry.Resolve<CommodityService>();
        private ShipmentOrderService shipmentOrderService;
        private static ShipperService shipperService = ComponentRegistry.Resolve<ShipperService>();
        public TradeController()
        {
            this.shipmentOrderService = ComponentRegistry.Resolve<ShipmentOrderService>();
        }
        [Route("v1/trade/{trade_code}/Paid")]
        [HttpPost]
        public JObject SetPaid(String trade_code,PaymentInfo paymentInfo)
        {
            var order = shipmentOrderService.GetByNo(trade_code);
            order.PaymentCompanyCode = paymentInfo.PaymentCompanyCode;
            order.PaymentIdNo = paymentInfo.PaymentIdNo;
            order.PaymentOrderNo = paymentInfo.PaymentOrderNo;
            order.Status = ShipmentOrderStatus.Paid;
            shipmentOrderService.Ship(order);
            JObject result = new JObject();
            result["trade_code"] = order.No;
            result["payment_company_code"] = order.PaymentCompanyCode;
            result["payment_id_no"] = order.PaymentIdNo;
            result["payment_order_no"] = order.PaymentOrderNo;
            result["status"] = order.Status.ToString();
  
            return result;
        }
        [Route("v1/trade/{trade_code}/Received")]
        [HttpPost]
        public JObject SetReceived(String trade_code)
        {
            var order = shipmentOrderService.GetByNo(trade_code);
                order.Status = ShipmentOrderStatus.Received;
            shipmentOrderService.Save(order);
            JObject result = new JObject();
            result["trade_code"] = order.No;
            result["status"] = order.Status.ToString();
  
            return result;
        }

        [Route("v1/trade/{trade_code}/LogisticsCode")]
        [HttpGet]
        public JObject GetLogisticsOrderNo(String trade_code)
        {
            var order = shipmentOrderService.GetByNo(trade_code);
            JObject result = new JObject();
            result["trade_code"] = order.No;
            result["logistics_code"] = order.LogisticsOrderNo;
            result["logistics_company_code"] = order.LogisticsCompanyCode;
            result["logistics_company_name"] = order.LogisticsCompanyName;

            return result;
        }


        [Route("v1/trade/{trade_code}/status")]
        [HttpGet]
        public JObject GetStatus(String trade_code)
        {
            var order = shipmentOrderService.GetByNo(trade_code);
            JObject result = new JObject();
            result["trade_code"] = order.No;
            switch (order.Status)
            {
                case ShipmentOrderStatus.Ordering:
                    result["status"] = "Pending";
                    break;
                case ShipmentOrderStatus.Shipped:
                    result["status"] = "Completed";
                    break;
                case ShipmentOrderStatus.Closed:
                    result["status"] = ShipmentOrderStatus.Closed.ToString();
                    break;
                default:
                    result["status"] = "Trading";
                    break;

            }
            return result;
        }
        [Route("v1/trade")]
        [HttpPost]
        public string Post(TradeInfo trade)
        {
            var order = BindToDomainModel(trade);
            shipmentOrderService.Create(order);
            var result = Newtonsoft.Json.JsonConvert.SerializeObject(BindToViewModel(order));
            return result;
        }
        private TradeInfo BindToViewModel(ShipmentOrder domaiShipmentOrder)
        {
            TradeInfo tradeInfo = AutoMapper.Mapper.Map<ShipmentOrder, TradeInfo>(domaiShipmentOrder);
            return tradeInfo;

        }
        private ShipmentOrder BindToDomainModel(TradeInfo viewTradeInfo)
        {
            ShipmentOrder shipmentOrder = AutoMapper.Mapper.Map<TradeInfo, ShipmentOrder>(viewTradeInfo);
            return shipmentOrder;
        }
        static TradeController()
        {
            AutoMapper.Mapper.CreateMap<TradeInfo, ShipmentOrder>()
                .ForMember(d => d.Shipper, s => s.MapFrom(t => shipperService.GetByCode(t.ShipperCode)))
                .ForMember(m => m.Items, o => o.Ignore()) // To avoid automapping attempt
                .AfterMap((p, o) => { o.Items = ToISet<TradeItemInfo, ShipmentOrderItem>(p.Items); });
            AutoMapper.Mapper.CreateMap<TradeItemInfo, ShipmentOrderItem>()
                .ForMember(d => d.Commodity, s => s.MapFrom(t => commodityService.GetByCode(t.CommodityCode)));

            AutoMapper.Mapper.CreateMap<ShipmentOrder, TradeInfo>();
            AutoMapper.Mapper.CreateMap<ShipmentOrderItem, TradeItemInfo>();
        }
        private static ISet<TDestination> ToISet<TSource, TDestination>(IEnumerable<TSource> source)
        {

            ISet<TDestination> set = null;
            if (source != null)
            {
                set = new HashSet<TDestination>();

                foreach (TSource item in source)
                {
                    set.Add(AutoMapper.Mapper.Map<TSource, TDestination>(item));
                }
            }
            return set;
        }
        private Dictionary<string, string> csvTradeColumns = new Dictionary<string, string>{
             {"No","原始订单号"},
            {"PaymentOrderNo","支付单号"},
             {"ReceiverName","收货人"},
            {"ReceiverIdNo","收货人身份证信息"},
             {"ReceiverAddress","收货人地址"},
             {"ReceiverMobile","收货人手机"}
        };
        private Dictionary<string, string> csvTradeItemColumns = new Dictionary<string, string>{
             {"CommodityName","产品名称"},
            {"FeatureName","规格"},
             {"CommodityQuantity","数量"}
        };
        [Route("v1/trade/csv/{shipperCode}")]
        [HttpGet]
        public HttpResponseMessage List(string shipperCode="311")
        {
            StringBuilder sb = new StringBuilder();
            List<string> csvColumns = new List<string>();
            csvColumns.AddRange(new string[] { "序号", "客户" });
            csvColumns.AddRange(csvTradeColumns.Values);
            csvColumns.AddRange(csvTradeItemColumns.Values);
            csvColumns.Add("申报日期");
            WriteCsv(sb, csvColumns);

            IEnumerable<ShipmentOrder> orders = this.shipmentOrderService.Query().Where(order =>
                order.Status == ShipmentOrderStatus.Ordering
                && order.Items.All(item => item.Commodity.ExternalShipperId.Equals(shipperCode))
                );
            int id = 1;
            foreach (var order in orders)
            {
                var itmes = order.Items;
                foreach (var item in itmes)
                {
                    //临时处理NHibernate代理类出现的异常
                    string feature = item.Commodity.FeatureName;
                    var commodityOfItem = item.Commodity;
                    item.Commodity = null;
                    order.Shipper = null;
                    order.Items = null;
                    order.ReceiverMobile = order.ReceiverMobile ?? order.ReceiverPhone;
                    order.ReceiverAddress = order.ReceiverProvince + order.ReceiverCity + order.ReceiverAddress;
                    JObject orderJObject = JObject.Parse(JsonConvert.SerializeObject(order, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }));
            
                    JObject itemJObject = JObject.Parse(JsonConvert.SerializeObject(item, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }));
                    item.Commodity = commodityOfItem;
                    itemJObject["FeatureName"] = feature;

                    List<string> cells = new List<string>();
                    cells.Add(id.ToString());
                    cells.Add("江苏跨境电子商务服务有限公司");
                    foreach (var key in csvTradeColumns.Keys)
                    {
                        string cell ="\t"+ orderJObject[key].ToString();
                        
                        cells.Add(cell);
                    }
                    foreach (var key in csvTradeItemColumns.Keys)
                    {
                        string cell = "\t" + itemJObject[key].ToString();
                        cells.Add(cell);
                    }
                    cells.Add(DateTime.Now.ToString("yyyyMMdd"));
                    WriteCsv(sb, cells);
                    id++;
                }

            }
            MemoryStream ms = new MemoryStream();
            byte[] bom = new byte[] { 0xEF, 0xBB, 0xBF };
            ms.Write(bom, 0, bom.Length);
            byte[] buffer = UTF8Encoding.UTF8.GetBytes(sb.ToString());
            ms.Write(buffer, 0, buffer.Length);
            ms.Position = 0;
            HttpContent content = new StreamContent(ms);
            content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
            content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = this.Url.Content(DateTime.Now.ToString("yyyyMMddHHmmss") + "-江苏跨境电子商务服务有限公司-订单.csv")
            };
            content.Headers.Expires = DateTimeOffset.Now;
            var response = this.Request.CreateResponse(HttpStatusCode.OK);
            response.Content = content;
            
            foreach (var order in orders) 
            {
               var orderObj = shipmentOrderService.FindById(order.Id);
               orderObj.Status = ShipmentOrderStatus.Ordered;
               shipmentOrderService.Save(orderObj);
            }
            return response;
        }
        private void WriteCsv(StringBuilder sb, List<String> cells)
        {
            for (int i = 0; i < cells.Count; i++)
            {

                if (i > 0)
                {
                    sb.Append(",");
                }

                sb.Append(cells[i]);

            }
            sb.AppendLine();
        }
    }
}
